package br.edu.ifrn.dominio;

import static javax.persistence.GenerationType.IDENTITY;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Persistence;

import br.edu.ifrn.dao.InstrumentoConclusaoDAO;
import br.edu.ifrn.dao.UsuarioDAO;
import br.edu.ifrn.exception.NegocioException;
import br.edu.ifrn.generic.GenericEntidade;
import br.edu.ifrn.utils.CriptografiaUtil;
import br.edu.ifrn.utils.ValidadorCampo;
import br.edu.ifrn.utils.ValidadorCampoUnico;

@NamedQueries({
	@NamedQuery(
			name="usuarioByLogin",
			query="SELECT u FROM Usuario u WHERE u.login = :login"
	)
})
@Entity
public class Usuario extends GenericEntidade implements Serializable{


	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	@Id
    @GeneratedValue(strategy=IDENTITY)
	protected Long id;
    
	private String nome;
	private String email;
	private String login;
	private String senha;
	private int disponibilidade;
	
	@OneToMany(mappedBy="orientador")
	private List<InstrumentoConclusao> instrumentosConclusao = new ArrayList<InstrumentoConclusao>();
	
	@ManyToOne
	private Diretoria diretoria;
	
	@OneToMany(mappedBy="coordenador")
	private List<Curso> cursosCordenados;
	
	@ManyToMany(fetch=FetchType.EAGER)
	private List<AreaAtuacao> areasAtuacao;
	
	@Enumerated(EnumType.STRING)
	private Perfil perfil;
	
	public Usuario(){
		this.setDisponibilidade(8);//seta a disponibilidade default
	}

	public Usuario(String nome, String email, String login, String senha,
			int disponibilidade, Perfil perfil, Diretoria diretoria) {
		super();
		this.nome = nome;
		this.email = email;
		this.login = login;
		this.senha = CriptografiaUtil.obterInstancia().criptografarComMD5(senha);
		this.disponibilidade = disponibilidade;
		this.diretoria = diretoria;
		this.perfil = perfil;
	}

	@Override
	public void validarImpl(List<String> erros) {
		ValidadorCampo.validarCampoVazio(this.nome, "nome", erros);
		ValidadorCampo.validarCampoVazio(this.email, "e-mail", erros);
		ValidadorCampo.validarCampoVazio(this.login, "login", erros);
		ValidadorCampo.validarCampoVazio(this.senha, "senha", erros);
		ValidadorCampo.validarTamanhoCampo(6, this.senha, "senha", erros);
		ValidadorCampo.validarCampoNulo(this.disponibilidade, "disponibilidade", erros);
		ValidadorCampo.validarCampoNulo(this.perfil, "perfil", erros);
		if(!this.isAdministrador()){
			ValidadorCampo.validarCampoNulo(this.diretoria, "diretoria", erros);
		}
		try {
			List<Usuario> usuarios = new UsuarioDAO().consultarTodos(" WHERE usuario.login = '"+this.login+"'", "");
			if(usuarios.size()!=0 && !usuarios.get(0).getId().equals(this.getId())){
				erros.add("Login já existente");
			}
		} catch (NegocioException e) {
			erros.add("Erro ao validar entidade");
		};
	}

	public String getNome() {
		return nome;
	}
	
	public void setNome(String nome) {
		this.nome = nome;
	}
	
	public String getEmail() {
		return email;
	}
	
	public void setEmail(String email) {
		this.email = email;
	}
	
	public String getLogin() {
		return login;
	}
	
	public void setLogin(String login) {
		this.login = login;
	}
	
	public String getSenha() {
		return senha;
	}
	
	public void setSenha(String senha) {
		this.senha = senha;
	}
	
	public Perfil getPerfil() {
		return perfil;
	}
	
	public void setPerfil(Perfil perfil) {
		this.perfil = perfil;
	}
	
	public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

	@Override
	public boolean equals(Object object) {
		if(object instanceof Usuario && ((Usuario)object).getId()==this.getId()){
			return true;
		}
		return false;
	}

	@Override
	public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
	}

	@Override
	public boolean isNewRecord() {
		return (this.id == null || this.id == 0); 
	}
	
	public boolean isAdministrador(){
		if(this.perfil!=null){
			return (this.perfil.equals(Perfil.Administrador));
		}else{
			return false;
		}
	}
	public boolean isCoordenador(){
		if(this.perfil!=null){
			return (this.perfil.equals(Perfil.Coordenador));
		}else{
			return false;
		}
	}
	public boolean isDiretor(){
		if(this.perfil!=null){
			return (this.perfil.equals(Perfil.Diretor));
		}else{
			return false;
		}
	}
	public boolean isProfessor(){
		if(this.perfil!=null){
			return (this.perfil.equals(Perfil.Professor));
		}else{
			return false;
		}
	}
	public void setDiretoria(Diretoria diretoria) {
		this.diretoria = diretoria;
	}

	public Diretoria getDiretoria() {
		return diretoria;
	}

	public void setCursosCordenados(List<Curso> cursosCordenados) {
		this.cursosCordenados = cursosCordenados;
	}

	public List<Curso> getCursosCordenados() {
		return cursosCordenados;
	}

	public void setAreasAtuacao(List<AreaAtuacao> areasAtuacao) {
		this.areasAtuacao = areasAtuacao;
	}

	public List<AreaAtuacao> getAreasAtuacao() {
		return areasAtuacao;
	}

	public void setDisponibilidade(int disponibilidade) {
		this.disponibilidade = disponibilidade;
	}

	public int getDisponibilidade() {
		return disponibilidade;
	}
	public int getDisponibilidadeReal() {
		int q = 0;
		for (InstrumentoConclusao ic : getInstrumentosAbertos()) {
			q+=ic.getTipoInstrumentoConclusao().getPeso();
		}
		if(this.getDisponibilidade() == 0){
			return 8-q;
		}else{
			return this.getDisponibilidade()-q;
		}
		
	}
	
	public boolean isDisponivel(){
		return this.getDisponibilidadeReal() > 0;
	}

	public List<InstrumentoConclusao> getInstrumentosAbertos(){
			try {
				return new InstrumentoConclusaoDAO().consultarTodos(" WHERE instrumentoConclusao.orientador.id = "+this.getId()+"" +
						" AND instrumentoConclusao.finalizado = 'false'", "");
			} catch (NegocioException e) {
				e.printStackTrace();
				return null;
			}
	}

	public void setInstrumentosConclusao(List<InstrumentoConclusao> instrumentosConclusao) {
		this.instrumentosConclusao = instrumentosConclusao;
	}

	public List<InstrumentoConclusao> getTodosInstrumentosConclusao() {
		try {
			return new InstrumentoConclusaoDAO().consultarTodos(" WHERE instrumentoConclusao.orientador.id = "+this.getId()+"", "");
		} catch (NegocioException e) {
			e.printStackTrace();
			return null;
		}
	}
	public List<InstrumentoConclusao> getInstrumentosConclusao() {
		return this.instrumentosConclusao;
	}
	
}
